package com.novax.ex.activity.provider.service;

import com.alibaba.fastjson.JSON;
import com.novax.ex.activity.infrastructure.entity.*;
import com.novax.ex.activity.infrastructure.mapper.*;
import com.novax.ex.activity.open.model.response.MallAdjustmentResponse;
import com.novax.ex.activity.open.model.response.MallPrizeResponse;
import com.novax.ex.activity.provider.handler.provider.MallOrderProvider;
import com.novax.ex.common.base.BaseMapper;
import com.novax.ex.common.base.BaseService;
import com.novax.ex.common.enums.MallPrizeOrderStatus;
import com.novax.ex.common.enums.MallPrizeStatus;
import com.novax.ex.common.enums.MallProductStatus;
import com.novax.ex.common.results.ReturnResult;
import com.novax.ex.common.util.CopyUtils;
import com.novax.ex.common.util.JWTUtil;
import com.novax.ex.common.util.PageQuery;
import com.novax.ex.common.util.PageUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 奖池商品表 service
 * @Author zhaolei
 * @Date 2/21/23 5:37 PM
 * @Version 1.0
 */
@Service
public class MallPrizeService extends BaseService {
    @Resource
    private MallPrizeMapper mallPrizeMapper;
    @Resource
    private MallConfigMapper mallConfigMapper;
    @Resource
    private MallPrizeOrderMapper mallPrizeOrderMapper;
    @Resource
    private MallOrderProvider mallOrderProvider;
    @Resource
    private MallProductTitleLanguageService mallProductTitleLanguageService;
    @Resource
    private MallProductBannerService mallProductBannerService;
    @Resource
    private MallProductDescriptionLanguageService mallProductDescriptionLanguageService;
    @Resource
    private MallProductMapper mallProductMapper;
    @Resource
    private MallPrizeLotteryService mallPrizeLotteryService;

    @Override
    protected BaseMapper getBaseMapper() {
        return mallPrizeMapper;
    }

    /**
     * @description: 添加奖品池商品
     * @author: Wade
     * @date: 2/21/23 7:05 PM
     * @param: [product]
     * @return: void
     **/
    @Transactional
    public void add(MallProduct product) {
        if (check(product)) {
            MallConfig mallConfig = mallConfigMapper.selectByCurrency(product.getCurrency());
            if (Objects.nonNull(mallConfig)) {
                MallPrize prize = CopyUtils.copyObject(product, MallPrize.class);
                prize.setId(null);
                prize.setMallProductId(product.getId());
                prize.setMinPrice(mallConfig.getMinPrice());
                prize.setStatus(1);
                prize.setCreateTime(null);
                prize.setUpdateTime(null);
                mallPrizeMapper.insertSelective(prize);
                //奖品池添加成功，更新商品上的期数
                mallProductMapper.addRound(product.getId());
            }
        }
    }

    /**
     * @description: 退款
     * @author: Wade
     * @date: 2/21/23 8:08 PM
     * @param: [product]
     * @return: void
     **/
    public void refund(MallProduct product) {
        //通过商品id查询奖品池状态为进行中的
        Map<String, Object> map = new HashMap<>();
        map.put("mallProductId", product.getId());
        map.put("status", MallPrizeStatus.start.getStatus());
        List<MallPrize> list = mallPrizeMapper.selectList(map);
        //发送退款
        if (!CollectionUtils.isEmpty(list)) {
            for (MallPrize prize : list) {
                Map<String, Object> mapOrder = new HashMap<>();
                mapOrder.put("mallProductId", product.getId());
                mapOrder.put("mallPrizeId", prize.getId());
                mapOrder.put("status", MallPrizeOrderStatus.stay.getStatus());
                List<MallPrizeOrder> orders = mallPrizeOrderMapper.selectList(mapOrder);
                if (!CollectionUtils.isEmpty(orders)) {
                    for (MallPrizeOrder order : orders) {
                        //按照下单记录进行发送退款消息
                        mallOrderProvider.sendRedund(JSON.toJSONString(order));
                    }
                }
                //更改奖池商品记录为退款状态
                MallPrize mallPrize = new MallPrize();
                mallPrize.setId(prize.getId());
                mallPrize.setStatus(MallPrizeStatus.refund.getStatus());
                mallPrizeMapper.updateByPrimaryKeySelective(mallPrize);
            }
        }
    }

    /**
     * @description: 检查是否可以添加到商品池
     * @author: Wade
     * @date: 2/21/23 7:26 PM
     * @param: [product]
     * @return: boolean
     **/
    private boolean check(MallProduct product) {
        if (Objects.nonNull(product)) {
            //上架状态判断
            if (product.getStatus().equals(MallProductStatus.up.getStatus())) {
                //库存判断
                if (product.getStockCount().intValue() > 0) {
                    //查询商品池中是否存在此商品并且是在进行中的，如果不存在则返回true,否则返回false
                    Map<String, Object> map = new HashMap<>();
                    map.put("mallProductId", product.getId());
                    map.put("status", MallPrizeStatus.start.getStatus());
                    List<MallPrize> list = mallPrizeMapper.selectList(map);
                    //如果没有则返回true
                    if (CollectionUtils.isEmpty(list)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }


    /**
     * @description: 奖品详情
     * @author: Wade
     * @date: 2/22/23 4:33 PM
     * @param: [language, id]
     * @return: com.novax.ex.activity.open.model.response.MallPrizeResponse
     **/
    public MallPrizeResponse detail(String language, String token, Long id) {
        MallPrize prize = find(id);
        if (Objects.nonNull(prize)) {
            MallPrizeResponse response = CopyUtils.copyObject(prize, MallPrizeResponse.class);
            //设置是否参与
            if (Objects.nonNull(token)) {
                Long userId = JWTUtil.getUid(token);
                Map<String, Object> mapOrder = new HashMap<>();
                mapOrder.put("mallPrizeId", id);
                mapOrder.put("userId", userId);
                mapOrder.put("status", MallPrizeOrderStatus.stay.getStatus());
                List<MallPrizeOrder> orders = mallPrizeOrderMapper.selectList(mapOrder);
                if(!CollectionUtils.isEmpty(orders)){
                    response.setStatus(2);
                }
            }
            response.setMaxBuyCount(getMaxBuyCount(response));
            //设置轮播
            response.setImgs(mallProductBannerService.getImgsByProductId(prize.getMallProductId()));
            //设置 title 展示名称
            response.setTitle(mallProductTitleLanguageService.getTitleByLanguage(prize.getMallProductId(), language));
            //设置 description 内容
            response.setDescription(mallProductDescriptionLanguageService.getDescriptionByLanguage(prize.getMallProductId(), language));
            return response;
        }
        return null;
    }

    /**
     * @description: 按照商品ID查询最新一期正在进行中的商品池记录，然后返回商品详情信息
     * @author: Wade
     * @date: 3/16/23 2:21 PM
     * @param: [language, token, productId]
     * @return: com.novax.ex.activity.open.model.response.MallPrizeResponse
     **/
    public MallPrizeResponse detailByProductId(String language, String token, Long productId){
        //根据商品ID反查出当前最新一期的奖品池记录
        Map<String, Object> map = new HashMap<>();
        map.put("mallProductId", productId);
        map.put("status", MallPrizeStatus.start.getStatus());
        List<MallPrize> list = mallPrizeMapper.selectList(map);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return detail(language,token,list.get(0).getId());
    }

    /**
     * @description: 返回最大可购买份数
     * @author: Wade
     * @date: 2/27/23 1:52 PM
     * @param: [response]
     * @return: java.lang.Integer
     **/
    private static Integer getMaxBuyCount(MallPrizeResponse response) {
        //最多可购分数 = 商品价格/最小单位价格-已售分数
        Integer maxBuyCount = response.getPrice().divide(response.getMinPrice(),BigDecimal.ROUND_CEILING).setScale( 0, BigDecimal.ROUND_UP ).intValue() - response.getSellCount();
        if(Objects.nonNull(maxBuyCount) && maxBuyCount.intValue()<0){
            maxBuyCount = 0;
        }
        return maxBuyCount;
    }

    public static void main(String[] args) {
        MallPrizeResponse response = new MallPrizeResponse();
        response.setPrice(new BigDecimal("0.3"));
        response.setMinPrice(new BigDecimal("1"));
        response.setSellCount(0);
        System.out.println(getMaxBuyCount(response));
    }

    /**
     * @description: 查询用户前台列表
     * @author: Wade
     * @date: 2/22/23 4:02 PM
     * @param: [language, userId, pageQuery]
     * @return: com.novax.ex.common.results.ReturnResult<com.novax.ex.common.util.PageUtil < com.novax.ex.activity.open.model.response.MallPrizeResponse>>
     **/
    public ReturnResult<PageUtil<MallPrizeResponse>> list(String language, String token, PageQuery pageQuery) {
        // todo 后期看压力，是否需要添加缓存
        PageUtil<MallPrizeResponse> page = new PageUtil<>(pageQuery);
        page.setCondition(Collections.singletonMap("query", pageQuery));
        findPage(page, MallPrizeResponse.class);
        List<MallPrizeResponse> responses = page.getItems();
        if (Objects.nonNull(responses)) {
            Map<Long, MallPrizeOrder> prizeOrderMap = new HashMap<>();
            //判断用户有没有登陆，如果登陆就获取用户订单列表是否有数据，有数据就
            if (Objects.nonNull(token)) {
                Long userId = JWTUtil.getUid(token);
                List<Long> prizeIds = responses.stream().map(MallPrizeResponse::getId).collect(Collectors.toList());
                Map<String, Object> mapOrder = new HashMap<>();
                mapOrder.put("mallPrizeIds", prizeIds);
                mapOrder.put("userId", userId);
                mapOrder.put("status", MallPrizeOrderStatus.stay.getStatus());
                List<MallPrizeOrder> orders = mallPrizeOrderMapper.selectList(mapOrder);
                prizeOrderMap = orders.stream().collect(Collectors.toMap(MallPrizeOrder::getMallPrizeId, obj -> obj, (key1, key2) -> key1));
            }
            //设置商品展示名称
            for (MallPrizeResponse prize : responses) {
                //设置语言
                prize.setTitle(mallProductTitleLanguageService.getTitleByLanguage(prize.getMallProductId(), language));
                //设置主图片
                prize.setImg(getMainImg(prize.getMallProductId()));
                //设置状态为参与过的
                if (prizeOrderMap.containsKey(prize.getId())) {
                    prize.setStatus(2);
                }
                prize.setMaxBuyCount(getMaxBuyCount(prize));
            }

        }
        return ReturnResult.success(page);
    }

    /**
     * @description: 设置列表主图
     * @author: Wade
     * @date: 3/16/23 11:54 AM
     * @param: []
     * @return: java.lang.String
     **/
    private String getMainImg(Long mallProductId){
        MallProduct mallProduct = mallProductMapper.selectByPrimaryKey(mallProductId);
        if(Objects.nonNull(mallProduct) && StringUtils.isNotBlank(mallProduct.getImage())){
            return mallProduct.getImage();
        }else{
            return mallProductBannerService.getByMainImg(mallProductId);
        }
    }

    /**
     * @description: 修改售价
     * @author: Wade
     * @date: 3/28/23 4:07 PM
     * @param: [product]
     * @return: void
     **/
    public MallPrizeLottery updatePrice(MallProduct product) {
        //通过商品id查询奖品池状态为进行中的
        Map<String, Object> map = new HashMap<>();
        map.put("mallProductId", product.getId());
        map.put("status", MallPrizeStatus.start.getStatus());
        List<MallPrize> list = mallPrizeMapper.selectList(map);
        //修改奖品池售价
        if (!CollectionUtils.isEmpty(list)) {
            //修改完售价之后判断最新的价格是否达到开奖条件，如果达到开奖条件，调用开奖逻辑
            for (MallPrize mallPrize : list) {
                boolean startLottery = false;
                MallPrize prize = new MallPrize();
                prize.setId(mallPrize.getId());
                prize.setPrice(product.getPrice());
                //如果售卖价格>=指定价格 设置为完成,这样后面的就不会在进来了
                if (mallPrize.getSellPrice().compareTo(prize.getPrice()) >= 0) {
                    //说明是需要开始抽奖的
                    prize.setStatus(MallPrizeStatus.over.getStatus());
                    startLottery = true;
                }
                mallPrizeMapper.updateByPrimaryKeySelective(prize);
                //修改订单上的售价
                mallPrizeOrderMapper.updatePrice(mallPrize.getId(),prize.getPrice());
                if(startLottery){
                    //需要进行开奖抽奖逻辑
                    return mallPrizeLotteryService.startLottery(mallPrize.getId());
                }
            }
        }
        return null;
    }

    /**
     * @description: 修改成本价
     * @author: Wade
     * @date: 3/28/23 4:07 PM
     * @param: [product]
     * @return: void
     **/
    public void updateCost(MallProduct product) {
        //通过商品id查询奖品池状态为进行中的
        Map<String, Object> map = new HashMap<>();
        map.put("mallProductId", product.getId());
        map.put("status", MallPrizeStatus.start.getStatus());
        List<MallPrize> list = mallPrizeMapper.selectList(map);
        //修改奖品池成本价
        if (!CollectionUtils.isEmpty(list)) {
            for (MallPrize mallPrize : list) {
                MallPrize prize = new MallPrize();
                prize.setId(mallPrize.getId());
                prize.setCost(product.getCost());
                prize.setCostCurrency(product.getCostCurrency());
                mallPrizeMapper.updateByPrimaryKeySelective(prize);
                //修改订单上的成本价
                mallPrizeOrderMapper.updateCost(mallPrize.getId(),prize.getCost(),prize.getCostCurrency());
            }
        }
    }

    // 历史调整分页
    public <T> void findAdjustmentPage(PageUtil<T> pageInfo, Class<T> clazz) {
        long total = mallPrizeMapper.countAdjustment(pageInfo);
        pageInfo.setTotal(total);
        if (total > 0) {
            pageInfo.setItems(CopyUtils.copyList(mallPrizeMapper.selectAdjustmentPage(pageInfo), clazz));
        } else {
            pageInfo.setItems(new ArrayList<>());
        }
    }

    // 历史调整分页
    public <T> void findHistoryPage(PageUtil<T> pageInfo, Class<T> clazz) {
        long total = mallPrizeMapper.countHistory(pageInfo);
        pageInfo.setTotal(total);
        if (total > 0) {
            pageInfo.setItems(CopyUtils.copyList(mallPrizeMapper.selectHistoryPage(pageInfo), clazz));
        } else {
            pageInfo.setItems(new ArrayList<>());
        }
    }
}
